from sqlmodel import Session, Field, select, and_, or_, func
from dependencies import engine, SessionDep
from typing import Union, List, Optional, Any
from common import exception
import models
import utility
import datetime


"""按照条件查询当前用户拥有权限查看的用户列表信息

Keyword arguments:
skip -- 起始位置(default 0)
limit -- 每页数量(default 20)
username -- 用户名
name -- 昵称/姓名
org_id -- 所属组织机构
is_active -- 启用/停用
user -- 登录用户信息
Return: system_users -- 用户数据
"""


def get_user(
    skip: int = 0,
    limit: int = 20,
    username: str | None = None,
    name: str | None = None,
    org_id: int | None = None,
    is_active: bool | None = None,
    user: models.SystemUser = None,
    session: SessionDep = Session(engine),
):
    # 查询全部组织机构
    orgs = session.exec(select(models.SystemOrg)).all()

    # 获取当前用户拥有权限的机构id列表
    user_access_org_ids = utility.general.get_node_ids(orgs, user.org_id)

    # 获取用户查询条件的组织机构id列表
    user_query_org_ids = utility.general.get_node_ids(orgs, org_id)

    # 获取当前用户拥有权限的组织机构id列表和用户查询条件的组织机构id列表的交集
    org_list_id = list(set(user_access_org_ids) & set(user_query_org_ids))

    # 查询条件（如果当前用户组织id为空，查询所有组织机构的用户）
    if user.org_id:
        conditions = [
            and_(
                models.SystemUser.org_id.in_(org_list_id),
                models.SystemUser.org_id == org_id if org_id else True,
            ),
            models.SystemUser.username.like(f"%{username}%") if username else True,
            models.SystemUser.name.like(f"%{name}%") if name else True,
            models.SystemUser.is_active == is_active if is_active is not None else True,
            models.SystemUser.is_deleted == False,
        ]
    else:
        print(22222222222222)
        conditions = [
            models.SystemUser.org_id == org_id if org_id else True,
            models.SystemUser.username.like(f"%{username}%") if username else True,
            models.SystemUser.name.like(f"%{name}%") if name else True,
            models.SystemUser.is_active == is_active if is_active is not None else True,
            models.SystemUser.is_deleted == False,
        ]

    # 查询用户列表
    items = session.exec(
        select(models.SystemUser)
        .where(*conditions)
        .offset(skip)
        .limit(limit)
        .order_by(models.SystemUser.updatetime.desc())
    ).all()

    # 查询总条数
    total_statement = (
        select(func.count()).select_from(models.SystemUser).where(*conditions)
    )

    total = session.exec(total_statement).one()  # 使用 one() 方法获取单个标量结果

    # 初始用户列表数据
    system_users = []

    for item in items:
        # 用户拥有的角色列表
        roles = item.roles

        # 过滤掉is_active为False的角色
        roles = [role for role in roles if role.is_active]

        # 用户列表转化成dict
        item = dict(item)

        # 将创建人和更新人ID转化成姓名，
        item["creator"] = session.get(models.SystemUser, item["create_id"]).name
        item["updater"] = session.get(models.SystemUser, item["update_id"]).name

        # 将组织机构ID转化成组织机构名称
        if item["org_id"]:
            item["org_name"] = session.get(models.SystemOrg, item["org_id"]).name
        else:
            item["org_name"] = None

        # 将角色列表添加到用户数据中
        item["roles"] = roles

        system_users.append(item)

    return system_users, total


"""后台获取当前用户信息

Keyword arguments:
username -- 用户名
Return: system_user -- 返回用户信息
"""


def get_current_user(
    username: str | None = None,
    session: SessionDep = Session(engine)
):
    try:
        # 查询条件
        conditions = [
            models.SystemUser.username == username if username else True,
            models.SystemUser.is_active == True,
            models.SystemUser.is_deleted == False,
        ]

        # 构建查询语句
        statement = select(models.SystemUser).where(*conditions)

        # 执行查询
        system_user = session.exec(statement=statement).one_or_none()

        return system_user
    except Exception as e:
        session.rollback()
        raise e


"""新增用户

Keyword arguments:
user_create -- 新增用户信息
user -- 当前用户信息
Return: system_user -- 返回用户信息
"""


def create_user(
    user_create: models.SystemUserCreate,
    user: models.SystemUser = None,
    session: SessionDep = Session(engine),
):

    # 校验用户id是否已存在
    if get_current_user(user_create.username, session):
        raise exception.create_http_exception(detail="用户名已存在")
    # 校验组织机构是否为空
    elif user_create.org_id == None:
        raise exception.create_http_exception(detail="组织机构不能为空")
    # 校验组织机构是否存在
    elif not session.get(models.SystemOrg, user_create.org_id):
        raise exception.create_http_exception(detail="组织机构不存在")
    # 校验新增后的组织超出当前用户的权限范围
    elif (
        utility.general.check_data_permission(user_create.org_id, user, session)
        == False
    ):
        raise exception.create_http_exception(
            detail="用户编辑的组织机构超出当前用户的权限范围"
        )
    # 校验role_ids是否为空
    elif not user_create.role_ids:
        raise exception.create_http_exception(detail="用户关联的角色不能为空")
    # 校验用户关联的角色是否存在
    for role_id in user_create.role_ids:
        # 查询角色数据
        role = session.get(models.SystemRole, role_id)

        # 校验角色id是否存在
        if not role:
            raise exception.create_http_exception(detail="用户关联的角色不存在")

    # 新增用户
    system_user = models.SystemUser(
        **dict(user_create),
        password=utility.security.get_hashed_password(),
        create_id=user.id,
        update_id=user.id,
        createtime=datetime.datetime.now(),
        updatetime=datetime.datetime.now(),
    )
    session.add(system_user)
    session.commit()
    session.refresh(system_user)

    # 新增用户关联角色
    for role_id in user_create.role_ids:
        # 查询角色数据
        role = session.get(models.SystemRole, role_id)

        # 校验角色id是否存在
        if not role:
            raise exception.create_http_exception(detail="用户关联的角色不存在")

        # 新增用户关联角色
        system_user_role_link = models.SystemUserRoleLink(
            user_id=system_user.id,
            role_id=role_id,
        )
        session.add(system_user_role_link)
        session.commit()
        session.refresh(system_user_role_link)

    return system_user


"""编辑用户数据

Keyword arguments:
argument -- description
Return: system_user -- 返回用户信息
"""


def update_user(
    id: int,
    user_update: models.SystemUserUpdate,
    user: models.SystemUser = None,
    session: SessionDep = Session(engine),
):
    # 获取用户信息
    system_user = session.get(models.SystemUser, id)

    # 校验用户id是否已存在
    if not system_user:
        raise exception.create_http_exception(detail="用户不存在")
    # 校验用户是否有权限编辑该用户
    elif (
        utility.general.check_data_permission(system_user.org_id, user, session)
        == False
    ):
        raise exception.create_http_exception(detail="用户无权限编辑该用户")
    # 校验用户名是否已存在
    elif (
        get_current_user(user_update.username, session)
        and system_user.username != user_update.username
    ):
        raise exception.create_http_exception(detail="用户名已存在")
    # 校验组织机构是否为空
    elif user_update.org_id == None:
        raise exception.create_http_exception(detail="组织机构不能为空")
    # 校验组织机构是否存在
    elif not session.get(models.SystemOrg, user_update.org_id):
        raise exception.create_http_exception(detail="组织机构不存在")
    # 校验编辑后的组织超出当前用户的权限范围
    elif (
        utility.general.check_data_permission(system_user.org_id, user, session)
        == False
    ):
        raise exception.create_http_exception(
            detail="用户编辑的组织机构超出当前用户的权限范围"
        )
    # 校验role_ids是否为空
    elif not user_update.role_ids:
        raise exception.create_http_exception(detail="用户关联的角色不能为空")
    # 校验用户关联的角色是否存在
    for role_id in user_update.role_ids:
        # 查询角色数据
        role = session.get(models.SystemRole, role_id)

        # 校验角色id是否存在
        if not role:
            raise exception.create_http_exception(detail="用户关联的角色不存在")

    # 更新用户信息
    for key, value in dict(user_update).items():
        if key != "role_ids":
            setattr(system_user, key, value)

    # 更新更新人id和更新时间数据
    system_user.update_id = user.id
    system_user.updatetime = datetime.datetime.now()

    # 保存用户信息
    session.commit()
    session.refresh(system_user)

    # 查询当前用户已关联的角色
    has_userrolelinks = session.exec(
        select(models.SystemUserRoleLink).where(models.SystemUserRoleLink.user_id == id)
    ).all()

    # 提取已关联的角色ids
    orginal_role_ids = [userrole.role_id for userrole in has_userrolelinks]

    # 新的关联的角色ids
    new_role_ids = user_update.role_ids

    # 计算需要新增的角色id
    add_role_ids = list(set(new_role_ids) - set(orginal_role_ids))

    # 计算需要删除的角色id
    delete_role_ids = list(set(orginal_role_ids) - set(new_role_ids))

    # 新增用户关联角色
    if add_role_ids:
        for role_id in add_role_ids:
            # 新增用户关联角色
            system_user_role_link = models.SystemUserRoleLink(
                user_id=system_user.id,
                role_id=role_id,
            )
            session.add(system_user_role_link)

    # 删除用户关联角色
    if delete_role_ids:
        for role_id in delete_role_ids:
            # 删除用户关联角色
            userrole = session.exec(
                select(models.SystemUserRoleLink).where(
                    and_(
                        models.SystemUserRoleLink.user_id == id,
                        models.SystemUserRoleLink.role_id == role_id,
                    )
                )
            ).one_or_none()
            session.delete(userrole)

    # 提交事务
    session.commit()
    session.refresh(system_user)

    return system_user


"""删除用户数据(软删除)

Keyword arguments:
ids -- 用户id列表
user -- 当前用户信息
Return: system_user -- 返回用户信息
"""


def delete_user(
    id: int, user: models.SystemUser = None, session: SessionDep = Session(engine)
):
    # 获取用户信息
    system_user = session.get(models.SystemUser, id)

    # 校验用户id是否已存在
    if not system_user:
        raise exception.create_http_exception(
            detail="id为{id}的用户不存在".format(id=id)
        )
    # 校验用户是否有权限操作该用户
    elif (
        utility.general.check_data_permission(system_user.org_id, user, session)
        == False
    ):
        raise exception.create_http_exception(
            detail="用户无权限删除该用户,id为{}".format(id)
        )

    # 删除用户信息，逻辑删除
    system_user.is_deleted = True
    system_user.update_id = user.id
    system_user.updatetime = datetime.datetime.now()

    # 保存用户信息
    session.commit()
    session.refresh(system_user)

    return system_user


"""重置密码

Keyword arguments:
id -- 用户id
user -- 当前用户信息
Return: system_user -- 返回用户信息
"""


def reset_password(
    id: int, 
    user: models.SystemUser = None, 
    session: SessionDep = Session(engine)
):
    # 获取用户信息
    system_user = session.get(models.SystemUser, id)

    # 校验用户id是否已存在
    if not system_user:
        raise exception.create_http_exception(detail="用户不存在")
    # 校验用户是否有权限操作该用户
    elif (
        utility.general.check_data_permission(system_user.org_id, user, session)
        == False
    ):
        raise exception.create_http_exception(detail="用户无权限操作该用户")

    # 重置密码
    system_user.password = utility.security.get_hashed_password()
    system_user.update_id = user.id
    system_user.updatetime = datetime.datetime.now()

    # 保存用户信息
    session.add(system_user)
    session.commit()
    session.refresh(system_user)

    return system_user


"""修改密码

Keyword arguments:
id -- 用户id
user -- 当前用户信息
Return: system_user -- 返回用户信息
"""


def modify_password(
    id: int,
    passwords: models.SystemUserModifyPassword,
    user: models.SystemUser = None,
    session: SessionDep = Session(engine),
):
    # 获取用户信息
    system_user = session.get(models.SystemUser, id)

    # 密码规范校验
    valid_password = utility.security.validate_password(passwords.new_password)

    # 校验用户id是否已存在
    if not system_user:
        raise exception.create_http_exception(detail="用户不存在")
    # 校验用户是否有权限操作该用户
    elif (
        utility.general.check_data_permission(system_user.org_id, user, session)
        == False
    ):
        raise exception.create_http_exception(detail="用户无权限操作该用户")
    # 校验旧密码是否正确
    elif not utility.security.verify_password(
        passwords.old_password, system_user.password
    ):
        raise exception.create_http_exception(detail="旧密码输入错误")
    elif valid_password[0] == False:
        raise exception.create_http_exception(detail=valid_password[1])

    # 修改密码
    system_user.password = utility.security.get_hashed_password(passwords.new_password)
    system_user.update_id = user.id
    system_user.updatetime = datetime.datetime.now()

    # 保存用户信息
    session.add(system_user)
    session.commit()
    session.refresh(system_user)

    return system_user
